home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / TurboTCP 2.0.1 / TurboTCP source / CTelnetInterp.cp < prev    next >
Encoding:
Text File  |  1994-07-02  |  7.9 KB  |  402 lines  |  [TEXT/MPCC]

  1. /*
  2. ** CTelnetInterp.cp
  3. **
  4. **    TurboTCP support library
  5. **    Generic Telnet protocol interpreter
  6. **
  7. **    Copyright © 1993-94, FrostByte Design / Eric Scouten
  8. **
  9. */
  10.  
  11.  
  12. #include "CTelnetInterp.h"
  13.  
  14. TCL_DEFINE_CLASS_M1(CTelnetInterp, CTCPEndpoint);
  15.  
  16.  
  17. //    —— constructor ——
  18.  
  19. /*______________________________________________________________________
  20. **
  21. ** constructor
  22. **
  23. **    Initialize the Telnet interpreter.
  24. **
  25. **        theDefaultPort (unsigned short):    default IP port number (the only required parameter)
  26. **        recBufferSize (unsigned long):        size of receive buffer to create
  27. **        autoReceiveSize (unsigned short):    number of entries in RDS for auto-receive,
  28. **                                        0 to disable autoreceiving
  29. **        autoReceiveNum (unsigned short):    number of auto-receive calls to issue at once
  30. **                                        must be at least 1
  31. **        doUseCName (Boolean):            TRUE to get canonical name of remote host
  32. **                                        whenever possible
  33. **
  34. */
  35.  
  36. CTelnetInterp::CTelnetInterp(unsigned short theDefaultPort, unsigned long recBufferSize,
  37.                         unsigned short autoReceiveSize, unsigned short autoReceiveNum,
  38.                         Boolean doUseCName)
  39.  
  40. : CTCPEndpoint(theDefaultPort, recBufferSize, autoReceiveSize, autoReceiveNum, doUseCName)
  41.  
  42. {
  43.     itsState = normalChar;
  44.     showFileName = FALSE;
  45. }
  46.  
  47.  
  48. //    —— Telnet command handling ——
  49.  
  50.         // If you wish to respond to specific Telnet commands, override these methods.
  51.         // You may ignore any or all of these methods.
  52.  
  53. /*______________________________________________________________________
  54. **
  55. ** ReceivedWill
  56. **
  57. **    Respond to a Telnet [IAC WILL option] sequence. Default method responds [WONT option].
  58. **    Override to implement any Telnet options, call this method to reject any unimplemented
  59. **    options.
  60. **
  61. **        theOption (uchar):    the option code
  62. **
  63. */
  64.  
  65. void CTelnetInterp::ReceivedWill(uchar theOption)
  66.  
  67. {
  68.     char respondStr[4];
  69.  
  70.  
  71.     // reject all options
  72.  
  73.     respondStr[0] = charIAC;
  74.     respondStr[1] = escWONT;
  75.     respondStr[2] = theOption;
  76.     respondStr[3] = '\0';
  77.     if (showDebug) {
  78.         PrintDebugStr("{IAC WONT");
  79.         PrintDebugCharNum(theOption, ' ', '}');
  80.     }
  81.     *this << respondStr;
  82. }
  83.  
  84.  
  85. /*______________________________________________________________________
  86. **
  87. ** ReceivedDo
  88. **
  89. **    Respond to a Telnet [IAC DO option] sequence. Default method responds [WONT option].
  90. **    Override to implement any Telnet options, call this method to reject any unimplemented
  91. **    options.
  92. **
  93. **        theOption (uchar):    the option code
  94. **
  95. */
  96.  
  97. void CTelnetInterp::ReceivedDo(uchar theOption)
  98.  
  99. {
  100.     char respondStr[4];
  101.  
  102.  
  103.     // reject all options
  104.     
  105.     respondStr[0] = charIAC;
  106.     respondStr[1] = escWONT;
  107.     respondStr[2] = theOption;
  108.     respondStr[3] = '\0';
  109.     if (showDebug) {
  110.         PrintDebugStr("{IAC WONT");
  111.         PrintDebugCharNum(theOption, ' ', '}');
  112.     }
  113.     *this << respondStr;
  114. }
  115.  
  116.  
  117. /*______________________________________________________________________
  118. **
  119. ** ReceivedSB
  120. **
  121. **    Receive subnegotiation parameters. Buffers characters until SE is received.
  122. **
  123. **        theChar (uchar):    the latest character
  124. **
  125. */
  126.  
  127. void CTelnetInterp::ReceivedSB(uchar theChar)
  128.  
  129. {
  130.     if (showDebug)
  131.         PrintDebugCharNum(theChar, ' ', '\0');
  132.     sbBfr[sbBfrIndex++] = theChar;
  133. }
  134.  
  135.  
  136. //    —— respond to incoming data (do not override) ——
  137.  
  138. /*______________________________________________________________________
  139. **
  140. ** HandleDataArrived (private method)
  141. **
  142. **    Process incoming data.
  143. **
  144. **        theData (void*):            pointer to the block of data
  145. **        theDataSize (unsigned short):    size of the data block
  146. **        isUrgent (Boolean):            TRUE if urgent data
  147. **
  148. */
  149.  
  150. void CTelnetInterp::HandleDataArrived(void* theData, unsigned short theDataSize, Boolean isUrgent)
  151.  
  152. {
  153.     char*    xData = (char*) theData;                // hack to avoid lots of typecasts
  154.     uchar    theChar;
  155.     char        theLine[83];
  156.     short    lineIndex;
  157.  
  158.  
  159.     // parse each character separately
  160.     
  161.     while (theDataSize--) {
  162.         theChar = (uchar) (*(xData++));
  163.  
  164.  
  165.         // respond to current Telnet state
  166.         
  167.         switch (itsState) {
  168.  
  169.  
  170.             // normal operation: write character
  171.             
  172.             case normalChar:
  173.  
  174.  
  175.                 // optimization: try to grab several chars at once
  176.                 
  177.                 lineIndex = 0;
  178.                 while ((theDataSize > 1) && (theChar >= ' ') && (theChar != charIAC)) {
  179.                     theDataSize++;
  180.                     xData--;
  181.                     lineIndex = 0;
  182.                     while ((theDataSize > 0) && (((uchar) *xData) >= ' ') &&
  183.                                             (*xData != charIAC) && (lineIndex < 80))
  184.                         theDataSize--, theLine[lineIndex++] = (uchar) *(xData++);
  185.                     if ((theDataSize > 0) && (*xData == charCR))
  186.                         theDataSize--, xData++, theLine[lineIndex++] = charCR;
  187.                     if ((theDataSize > 0) && (*xData == charLF))
  188.                         theDataSize--, xData++, theLine[lineIndex++] = charLF;
  189.                     theLine[lineIndex] = '\0';
  190.                     if (lineIndex)
  191.                         HandleNVTLine((char*) &theLine[0]);
  192.                     if (theDataSize < 1)
  193.                         break;
  194.                     theChar = (uchar) (*(xData++));
  195.                     theDataSize--;
  196.                 }
  197.                 
  198.                 if ((lineIndex) && !(theDataSize))
  199.                     break;
  200.  
  201.  
  202.                 // end of loop: test for IAC
  203.                 
  204.                 if (theChar == charIAC) {
  205.                     itsState = gotIAC;
  206.                     if (showDebug)
  207.                         PrintDebugStr("[IAC");
  208.                 }
  209.                 else
  210.                     HandleNVTChar(theChar);
  211.                 break;
  212.  
  213.  
  214.             // received IAC (interpret as command)
  215.             
  216.             case gotIAC:
  217.             case gotIACinSB:
  218.                 ReceivedIAC(theChar);
  219.                 break;
  220.  
  221.  
  222.             // handle other cases
  223.                 
  224.             case gotSB:
  225.                 if (theChar == charIAC) {
  226.                     itsState = gotIACinSB;
  227.                     if (showDebug)
  228.                         PrintDebugStr(" IAC");
  229.                 }
  230.                 else
  231.                     ReceivedSB(theChar);
  232.                 break;
  233.  
  234.             case gotWILL:
  235.                 if (showDebug)
  236.                     PrintDebugCharNum(theChar, ' ', ']');
  237.                 ReceivedWill(theChar);
  238.                 itsState = normalChar;
  239.                 break;
  240.  
  241.             case gotWONT:
  242.                 if (showDebug)
  243.                     PrintDebugCharNum(theChar, ' ', ']');
  244.                 ReceivedWont(theChar);
  245.                 itsState = normalChar;
  246.                 break;
  247.  
  248.             case gotDO:
  249.                 if (showDebug)
  250.                     PrintDebugCharNum(theChar, ' ', ']');
  251.                 ReceivedDo(theChar);
  252.                 itsState = normalChar;
  253.                 break;
  254.  
  255.             case gotDONT:
  256.                 if (showDebug)
  257.                     PrintDebugCharNum(theChar, ' ', ']');
  258.                 ReceivedDont(theChar);
  259.                 itsState = normalChar;
  260.                 break;
  261.         }
  262.     }
  263.  
  264. }
  265.  
  266.  
  267. /*______________________________________________________________________
  268. **
  269. ** ReceivedIAC
  270. **
  271. **    Respond to a Telnet [IAC command] sequence.
  272. **
  273. **        theCommand (uchar):    the command code
  274. **
  275. */
  276.  
  277. void CTelnetInterp::ReceivedIAC(uchar theCommand)
  278.  
  279. {
  280.  
  281.     // which command is it?
  282.  
  283.     switch (theCommand) {
  284.  
  285.         case escSE:
  286.             if (showDebug)
  287.                 PrintDebugStr(" SE]");
  288.             sbBfr[sbBfrIndex] = '\0';
  289.             if (itsState == gotIACinSB)
  290.                 ReceivedSE();
  291.             itsState = normalChar;
  292.             break;
  293.  
  294.         case escNOP:
  295.             if (showDebug)
  296.                 PrintDebugStr(" NOP]");
  297.             itsState = normalChar;
  298.             break;
  299.             
  300.         case escDM:
  301.             if (showDebug)
  302.                 PrintDebugStr(" DM]");
  303.             ReceivedSynch();
  304.             itsState = normalChar;
  305.             break;
  306.             
  307.         case escBRK:
  308.             if (showDebug)
  309.                 PrintDebugStr(" BRK]");
  310.             ReceivedBRK();
  311.             itsState = normalChar;
  312.             break;
  313.             
  314.         case escIP:
  315.             if (showDebug)
  316.                 PrintDebugStr(" IP]");
  317.             ReceivedIP();
  318.             itsState = normalChar;
  319.             break;
  320.             
  321.         case escAO:
  322.             if (showDebug)
  323.                 PrintDebugStr(" AO]");
  324.             ReceivedAO();
  325.             itsState = normalChar;
  326.             break;
  327.             
  328.         case escAYT:
  329.             if (showDebug)
  330.                 PrintDebugStr(" AYT]");
  331.             ReceivedAYT();
  332.             itsState = normalChar;
  333.             break;
  334.             
  335.         case escEC:
  336.             if (showDebug)
  337.                 PrintDebugStr(" EC]");
  338.             ReceivedEC();
  339.             itsState = normalChar;
  340.             break;
  341.             
  342.         case escEL:
  343.             if (showDebug)
  344.                 PrintDebugStr(" EL]");
  345.             ReceivedEL();
  346.             itsState = normalChar;
  347.             break;
  348.             
  349.         case escGA:
  350.             if (showDebug)
  351.                 PrintDebugStr(" GA]");
  352.             ReceivedGA();
  353.             itsState = normalChar;
  354.             break;
  355.             
  356.         case escSB:
  357.             if (showDebug)
  358.                 PrintDebugStr(" SB");
  359.             itsState = gotSB;
  360.             sbBfrIndex = 0;
  361.             break;
  362.         
  363.         case escWILL:
  364.             if (showDebug)
  365.                 PrintDebugStr(" WILL");
  366.             itsState = gotWILL;
  367.             break;
  368.             
  369.         case escWONT:
  370.             if (showDebug)
  371.                 PrintDebugStr(" WONT");
  372.             itsState = gotWONT;
  373.             break;
  374.         
  375.         case escDO:
  376.             if (showDebug)
  377.                 PrintDebugStr(" DO");
  378.             itsState = gotDO;
  379.             break;
  380.         
  381.         case escDONT:
  382.             if (showDebug)
  383.                 PrintDebugStr(" DONT");
  384.             itsState = gotDONT;
  385.             break;
  386.         
  387.         case escIAC:
  388.         default:
  389.             if (itsState == gotIACinSB) {
  390.                 ReceivedSB(theCommand);
  391.                 itsState = gotIAC;
  392.             }
  393.             else {
  394.                 if (showDebug)
  395.                     PrintDebugCharNum(theCommand, '?', ']');
  396.                 HandleNVTChar(theCommand);
  397.                 itsState = normalChar;
  398.             }
  399.     }
  400.  
  401. }
  402.